Form.php

<?php

namespace Fresh;

class Form extends View {


    public function initialize(){
        $this->addQuery('//form',[$this,'handleForm']);
        $this->addCompileHandler('form-input',[$this,'handleFormInput']);
        // $this->addRuntimeHandler('find',[$this,'find']);
        // $this->setRuntimeHandler('formatObjectValue',[$this,'formatObjectValue']);
        // $this->addFormatter('markdown',[$this,'mdToHtml']);
    }

    protected function fileFor($viewName){
        $viewName .= 'Form';
        $file = $this->component->dir.'/view/'.$viewName.'.php';
        return $file;
    }
    protected function compileFileFor($viewName){
        $viewName .= 'Form';
        return $this->component->dir.'/compiled/'.$viewName.'.php';
    }

    protected function handleFormInput($compiler,$inputNode,$table){

        $varName = $table;

        $propName = $inputNode->getAttribute('name');        

        $placeholder = $compiler->placeholderFor('<?=$'.$varName.'->'.$propName.'; ?>');
        

        if (strtolower($inputNode->getAttribute('type'))=='file'){
            $form = $inputNode->form;
            $form->enctype = "multipart/form-data";
        } else if (strtolower($inputNode->getAttribute('type'))=='checkbox'){
            $placeholder = $compiler->placeholderFor('<?=((bool)$'.$varName.'->'.$propName.') ? " checked" : ""; ?>');
            $inputNode->setAttribute($placeholder,'');
            // $inputNode->setAttribute('checked','should this be?');
        } else if (strtolower($inputNode->tagName)=='textarea'){
            $inputNode->innerHTML = $placeholder;
        } else if (strtolower($inputNode->tagName)=='input'){
            $inputNode->setAttribute('value',$placeholder);
        } else if (strtolower($inputNode->tagName)=='img'){
            $inputNode->src = $placeholder;
        } 
        
    }

    protected function handleForm(\Taeluf\PHTML $doc, \Fresh\Form $form, \Taeluf\PHTML\Compiler $compiler, \Taeluf\PHTML\Node $node){

            //cleanse the form of php
                //load the view which this form relates to
            // get the list of entities from the view
            // get the first entity
            // get the table
            // set input values & innertexts to print the database value
            // output the compiled form

        // Add "smarter" value-setting for input types like select or textarea
        // Add enctype (if file input found),method,action to form

        // compile an id-based lookup for that table

        $placeholder = $compiler->placeholderFor($node);
        $node->parentNode->replaceChild($doc->createTextNode($placeholder),$node);
        $node->addHiddenInput('id','');

        $view = $this->view();
        $entities = $view->getEntities();
        $entity = $entities[0] ?? null;
        if ($entity==null)throw new \Exception("We could not find a view for this form named '{$form->name}'");

        foreach ($this->handler->compile->form??[] as $handler){
            $handler($form,$doc,$compiler,$node);
        }
        // var_dump($routes);
        // exit;

        $table = $entity->getAttribute('rb-table');
        // $lookup = 'id:<?=$id? >';
        $varName = $table;


        $inputNodes = $doc->xpath('.//*[@name]',$node);
        foreach ($inputNodes as $input){
            $this->executeCompileHandlers('form-input',$compiler,$input,$table);
        }

        $node->action = $compiler->placeholderFor("<?=\$submit_url;?>");
        $node->method = 'POST';
        $node->addHiddenInput('fresh_table',$table);


        $escTable = var_export($table,true);
            /**
             * Call `$compo->addCompileHandler('Form.EntityLoop.Start', $callable)`  
             * `$callable` should:
             * - Accept NO paramaters
             * - Return a string of valid PHP code
             *    - DO NOT include open & close tags @ beginning and end of your code.
             *       - You MAY close & re-open amidst your code.
             * 
             * @TODO Maybe pass some paramaters to the callable???
             * 
             * @export(Handler.Compile.Form_Entity_Loop_Start)
             */
            $loopStartCode = $this->executeCompileHandlers('Form.EntityLoop.Start');
            $formLoopStartCode = implode("\n",$loopStartCode);

        $phpOpen = 
        <<<PHP

            <?php
                \$table = {$escTable};
                \$find = 'id:'.\$id.';';
                \$list = \$this->callHandler('find',\$table,\$find);
                foreach (\$list as \$rb_object){ 
                    \${$varName} = \$rb_object; 
                    {$formLoopStartCode}
                    ?>

        PHP;
        $compiler->placeholderPrepend($placeholder,$phpOpen);


        $phpClose = 
        <<<PHP

            <?php 
                }
            ?>

        PHP;
        $compiler->placeholderAppend($placeholder,$phpClose);
        
        
        return;

    }
    
    /**
     * Get an array of elements which are:
     *  1. child of a <form> tag
     *  2. Have a name attribute
     *  3. NOT a <form> tag itself
     *
     * @return an array of elements or an empty array if none found
     */
    public function getInputs(){
        $compiler = new \Taeluf\PHTML\Compiler();
        $dirtySource = file_get_contents($this->file);
        $cleanSource = $compiler->cleanSource($dirtySource);
        $preDocHandlers = $this->handler->compile->preDoc ?? [];
        foreach ($preDocHandlers as $handler){
            $cleanSource = $handler($cleanSource,$dirtySource,$compiler,$this);
        }

        $doc = new \Taeluf\PHTML($cleanSource);
        $inputs = $doc->xpath('//form//*[@name]');
        $list=[];
        foreach ($inputs as $i)if (strtolower($i->tagName)!='form')$list[] = $i;
        return $list;
    }
}